home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
DDJMAG
/
DDJ9207.ZIP
/
AVKCAPT.ZIP
/
ACMAIN.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-01
|
21KB
|
790 lines
//-------------------------------------------------------------------------
// ActionMedia II Programmer's Toolkit
//
// Windows Motion Capture Sample Program
//
// Application: AvkCapt.exe
// Module Name: acmain.c
//
// Description: Main module for avk motion capture program.
// Contains program entry point (WinMain), windows
// message processing functions, and dialog box procs.
//
// Copyright Intel Corp. 1991, 1992
// All Rights Reserved.
//
//-------------------------------------------------------------------------
//
// Exported functions from this module:
//
// WinMain
// MainWndProc
// AboutDlgProc
// OpenFileDlgProc
//
//-------------------------------------------------------------------------
//
// Functions local to this module:
//
// InitApplication
// InitInstance
// MsgCommand
// GetFileName
//
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
//
// NOTES ON AvkCapt
//
// AvkCapt is a simple motion capture program. It premonitors from
// the digitizer on CS2, the capture board. When the user toggles
// on Capture, AvkCapt begins capturing the incoming frames and writing
// them out to a file.
//
// AvkCapt uses the AVKIO file I/O subsystem to create an AVSS file and
// to manage writing and updating the header information. Video and
// audio frames are retrieved separately from their respective buffers.
// The AVKIO function AvioFileFrmWrite() is used to write interleaved
// video and audio frames to the AVSS file.
//
// AvkCapt will capture either NTSC 30-fps or PAL 25-fps files using the
// RTV 2.0 compression algorithm for video and the ADPCM4 algorithm for
// audio. It calls AvkDeviceVideoIn to determine the capture source sync.
// It formats a video stream to 128x240 (NTSC) or 128x244 (PAL) for
// capture. Since RTV 2.0 will double the horizontal pixels, the
// end result is a 256x240 (NTSC) or 256x288 (PAL) file for later
// playback. Since the horizontal resolution of the playback stream
// is only 128, though, we can't show the premonitored video at
// full-screen size on our 256x240 VGA view. This is because we can't
// scale up using a connector. In AVK, if the destination is larger than
// the source, the image will be displayed in the upper left hand corner
// of the destination box. Therefore, AvkCapt uses a fixed window of
// 128x120 pixels to display the premonitored video.
//
// The most difficult element of capturing incoming digitized data is
// keeping up with it. If an AVK program does not read the frames
// from the VRAM buffers fast enough with calls to AvkGrpBufRead(), then
// frames will be lost and a series of blank frames will be inserted to
// take their place causing skipping effects on playback. On the other
// hand, if the program spends too much time retrieving data, it may be
// neglecting to process the message loop promptly and mouse action may
// degrade.
//
// There are basically two different approaches to retrieving data in a
// timely manner. AvkCapt gives simple examples of both. The first
// technique involves calling our read routine each time AvkCapt receives
// a message from AVK informing it that a designated amount of data has
// been captured into a VRAM Group Buffer. AVK sends the
// AVK_CAPTURE_DATA_AVAILABLE message whenever the data in a VRAM buffer
// exceeds the hunger granularity level the application has set when
// creating the Group Buffer. The read routine then retrieves as much
// data from the VRAM buffer as it can handle, parses it into frames and
// writes out as many frames as it can to the AVSS file before exiting.
// The application returns to processing the message loop and awaits the
// next AVK_CAPTURE_DATA_AVAILABLE message.
//
// The second method (enabled by selecting the 'Timer' option from the
// 'File' popup menu) involves setting up a Windows timer and calling
// the same read routine on each timer tick. Note that we are using a
// timer tick of 200 milliseconds to call CaptureAvioData(). This will
// result in a maximum of approximately 5 calls per second. The capture
// function has to write about 6 frames a call to keep up. Since
// CaptureAvioData() is likely to write out more than that if more data
// is present, timer messages may back up. Windows will discard backed
// up timer ticks if one is already waiting in the queue, so this is
// no problem. The TIMER_INTERVAL #define in AvkCapt.h can be altered
// to change this interval.
//
// AvkCapt's performance in capturing can be tuned by varying the above-
// mentioned TIMER_INTERVAL, the #defined value for CAPTURE_LOOPS (which
// dictates how many iterations of the read/write loop will be executed
// in CaptureAvioData() before it is forced back to the main message
// loop) and the #defined size of the host buffers, HOST_BUF_SIZE.
//
// An additional improvement may be obtained by changing the timer
// tick logic to have the timer call CaptureAvioData() directly (don't
// forget to use a Proc Instance for this).
//
//-------------------------------------------------------------------------
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include "avkapi.h"
#include "avkcapt.h"
#include "disperr.h"
#include "avkio.h"
#include "log.h"
//-------------------------------------------------------------------------
// Local variables
//-------------------------------------------------------------------------
HWND hwndMain;
HANDLE hInst;
char szMainMenu[] = "MainMenu"; // main menu name
char szWndClass[] = "AvkCaptClass"; // main window class
char AvssFileName[128] = {'\0'}; // we build the AVSS file name here
BOOL bDstBoxInitialized = FALSE; // TRUE after View.DstBox is first set
BOOL bTimedCapture = FALSE; // TRUE if timed capturing selected
char *pStateName[] =
{
"UNINITIALIZED",
"INITIALIZED",
"MONITORING",
"CAPTURING"
};
//-------------------------------------------------------------------------
// External functions.
//-------------------------------------------------------------------------
extern BOOL InitAvk(void);
extern BOOL CreateAvkResources(WORD);
extern BOOL EndAvk(void);
extern BOOL MonitorOn(void);
extern BOOL MonitorOff(void);
//-------------------------------------------------------------------------
// Local functions.
//-------------------------------------------------------------------------
LONG FAR PASCAL MainWndProc(HWND, WORD, WORD, LONG);
BOOL FAR PASCAL AboutDlgProc(HWND, WORD, WORD, LONG);
BOOL FAR PASCAL OpenDlgProc(HWND, WORD, WORD, LONG);
BOOL InitApplication(HANDLE);
BOOL InitInstance(HANDLE, int);
BOOL MsgCommand(HWND, WORD, WORD, LONG);
BOOL GetFileName(HWND);
//--------------------------------------------------------------------------
//FUNCTION:
//
// int WinMain(hInst, hPrevInst, lpszCmdLine, nCmdShow)
//
//PARMS IN:
//
// HANDLE hInst this instance's handle
// HANDLE hPrevInst handle to previous instance or NULL
// if no previous instance exists
// LPSTR lpszCmdLine far pointer to the command line string
// int nCmdShow whether to show an icon or the window
//
//DESCRIPTION:
//
// Windows entry point. It initializes the application and instance
// data. Prevents multiple instances. It then opens the AVK session and
// enters the Windows message loop. On exit, it closes the AVK session.
//
//RETURN:
//
// 16-bit parameter value from WM_QUIT message.
//
//-------------------------------------------------------------------------
int PASCAL
WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR pCmdLine, int nCmdShow)
{
MSG Msg;
int Ret = 0;
// Prevent multiple instances.
if (!hPrevInstance)
{
// Initialize window data and register the main and
// image window classes.
if (InitApplication(hInstance))
{
// Create main window and the image display window.
if (InitInstance(hInstance, nCmdShow))
{
MessageBox(GetFocus(),
"Do not switch to a full-screen DOS "
"session while Monitoring is On.",
"AvkCapt", MB_ICONASTERISK | MB_OK);
// Open an AVK session.
if (InitAvk())
{
// Operate the message loop
// until a WM_QUIT is received.
while (GetMessage(&Msg, NULL, NULL, NULL))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
// Close AVK and return the PostQuit message's
// wParam value.
EndAvk();
Ret = Msg.wParam;
}
}
}
else
// Oops, another instance is running. Display an error
// message and go away.
MessageBox(GetFocus(), "Another instance is already running",
"AvkCapt", MB_ICONASTERISK | MB_OK);
return Ret;
}
//-------------------------------------------------------------------------
//FUNCTION:
//
// BOOL InitApplication(hInst)
//
//PARMS IN:
//
// HANDLE hInst handle for current instance
//
//DESCRIPTION:
//
// Initializes the windows data and registers the window class.
//
//RETURN:
//
// Value returned from call to RegisterClass().
//
//-------------------------------------------------------------------------
BOOL
InitApplication(HANDLE hInstance)
{
WNDCLASS Wc;
Wc.style = CS_HREDRAW | CS_VREDRAW;
Wc.lpfnWndProc = MainWndProc;
Wc.cbClsExtra = 0;
Wc.cbWndExtra = 0;
Wc.hInstance = hInstance;
Wc.hIcon = LoadIcon(hInstance, "AvkCaptIcon");
Wc.hCursor = LoadCursor(NULL, IDC_ARROW);
Wc.hbrBackground = GetStockObject(BLACK_BRUSH);
Wc.lpszMenuName = szMainMenu;
Wc.lpszClassName = szWndClass;
return RegisterClass(&Wc);
}
//-------------------------------------------------------------------------
//FUNCTION:
//
// BOOL InitInstance(HANDLE, int)
//
//PARMS IN:
//
// HANDLE hInstance handle for current instance
// int nCmdShow show as window or icon
//
//DESCRIPTION:
//
// Saves the instance handle to a global and creates the main window.
//
//RETURN:
//
// TRUE if window is created.
// FALSE if call to CreateWindow() failed.
//
//-------------------------------------------------------------------------
BOOL
InitInstance(HANDLE hInstance, int nCmdShow)
{
WORD cxScrn,cyScrn;
WORD cxWindow, cyWindow;
RECT Rect;
DWORD Style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU;
cxScrn = GetSystemMetrics(SM_CXSCREEN);
cyScrn = GetSystemMetrics(SM_CYSCREEN);
Rect.left = 0;
Rect.top = 0;
Rect.right = cxScrn >> 1;
Rect.bottom = cyScrn >> 1;
AdjustWindowRect((LPRECT)&Rect, Style, TRUE);
cxWindow = Rect.right - Rect.left;
cyWindow = Rect.bottom - Rect.top;
hInst = hInstance; // save the instance handle
// Get the screen coordinates.
hwndMain = CreateWindow(
szWndClass,
"AvkCapt - UNINITIALIZED",
Style,
(cxScrn - cxWindow) >> 1,
(cyScrn - cyWindow) >> 1,
cxWindow,
cyWindow,
NULL,
NULL,
hInstance,
NULL);
if (!hwndMain)
return FALSE;
ShowWindow(hwndMain, nCmdShow);
UpdateWindow(hwndMain);
LogOpen("DC.LOG");
return TRUE;
}
//-------------------------------------------------------------------------
//FUNCTION:
//
// long FAR PASCAL MainWndProc(HWND hWnd, WORD Msg, WORD wParam, LONG lParam)
//
//PARMS IN:
//
// HWND hWnd; window handle
// WORD Msg; type of message
// WORD wParam; 16-bit message parameter
// LONG lParam; 32-bit message parameter
//
//DESCRIPTION:
//
// Main window proc - processes messages received by the main window.
//
//RETURN:
//
// TRUE if window is created.
// FALSE if call to CreateWindow() failed.
//
//-------------------------------------------------------------------------
long FAR PASCAL
MainWndProc(HWND hWnd, WORD Msg, WORD wParam, LONG lParam)
{
switch (Msg)
{
case WM_TIMER:
if (bTimedCapture && IsState(ST_CAPTURING))
{
if (!CaptureAvioData())
DestroyWindow(hWnd);
}
return 0L;
case WM_MOVE:
if (!SetDstBox(hWnd))
DestroyWindow(hWnd);
return 0L;
case WM_SIZE:
return 0L;
case WM_COMMAND:
if (!MsgCommand(hWnd, Msg, wParam, lParam))
DestroyWindow(hWnd);
return 0L;
case AVK_CAPTURE_DATA_AVAILABLE:
// AVK has notified us that capture data is waiting
// to be written out.
if (!bTimedCapture && IsState(ST_CAPTURING))
{
if (!CaptureAvioData())
DestroyWindow(hWnd);
}
return 0L;
case AVK_GROUP_PAUSED:
// Receipt of paused message indicates capture off.
ToState(ST_MONITORING);
return 0L;
case AVK_IDENTIFY:
// We requested the digitizer source sync
// (NTSC vs PAL) during initialization.
// AVK_IDENTIFY has that sync value as the low word
// of lParam. Continue initializing
// now that we have the sync.
if (!CreateAvkResources(LOWORD(lParam)))
DestroyWindow(hWnd);
return 0L;
case WM_DESTROY:
// Just in case we get closed while capturing,
// close the capture file in an orderly manner.
// This causes final update information to be
// written to the file preventing a corrupted
// AVSS file.
CloseAvioFile();
if (bTimedCapture)
KillTimer(hWnd, TIMER_ID);
PostQuitMessage(0);
return 0L;
}
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
//-------------------------------------------------------------------------
//FUNCTION:
//
// LONG MsgCommand(hWnd, Msg, wParam, lParam)
//
//PARMS IN:
//
// HWND hWnd; // window handle
// WORD Msg; // message
// WORD wParam; // 16-bit message parameter
// LONG lParam; // 32-bit message parameter
//
//PARMS OUT:
//
// None
//
//DESCRIPTION:
//
// Processes WM_COMMAND messages for the Main Window Proc.
//
//RETURN:
//
// TRUE on success
// FALSE on error from AVK
//
//-------------------------------------------------------------------------
BOOL
MsgCommand(HWND hWnd, WORD Msg, WORD wParam, LONG lParam)
{
FARPROC lpThunk;
switch (wParam)
{
case IDM_EXIT:
CloseAvioFile();
return FALSE;
break;
case IDM_OPEN:
if (GetFileName(hWnd))
{
if (!OpenAvioFile(AvssFileName))
return FALSE;
EnableMenuItem(GetMenu(hWnd), IDM_OPEN, MENUITEM_OFF);
EnableMenuItem(GetMenu(hWnd), IDM_CLOSE, MENUITEM_ON);
}
break;
case IDM_CLOSE:
if (!CloseAvioFile())
return FALSE;
EnableMenuItem(GetMenu(hWnd), IDM_OPEN, MENUITEM_ON);
EnableMenuItem(GetMenu(hWnd), IDM_CLOSE, MENUITEM_OFF);
break;
case IDM_ABOUT:
lpThunk = MakeProcInstance(AboutDlgProc, hInst);
DialogBox(hInst, "AboutBox", hWnd, lpThunk);
FreeProcInstance(lpThunk);
break;
case IDM_MONITOR:
if (!ToggleMonitor())
return FALSE;
break;
case IDM_CAPTURE:
if (!ToggleCapture())
return FALSE;
break;
case IDM_TIMER:
if (bTimedCapture = !bTimedCapture)
{
if (!SetTimer(hWnd, TIMER_ID, TIMER_INTERVAL, NULL))
bTimedCapture = FALSE;
}
else
KillTimer(hWnd, TIMER_ID);
CheckMenuItem(GetMenu(hWnd), IDM_TIMER, bTimedCapture ?
MF_CHECKED : MF_UNCHECKED);
break;
}
return TRUE;
}
//-------------------------------------------------------------------------
//FUNCTION:
//
// BOOL FAR PASCAL About(HWND hDlg, WORD Msg, WORD wParam, LONG lParam)
//
//PARMS IN:
//
// HWND hDlg; window handle for the dialog box
// WORD Msg; type of message
// WORD wParam; 16-bit message parameter
// LONG lParam; 32-bit message parameter
//
//PARMS OUT:
//
// None
//
//DESCRIPTION:
//
// About Box Dlg Proc - processes the About dialog box messages - exits
// when the OKAY button is pressed or the system menu is used to close
// the dialog box.
//
//RETURN:
//
// TRUE if an IDOK message is received.
// FALSE if an IDCANCEL message is received
//
//-------------------------------------------------------------------------
BOOL FAR PASCAL
AboutDlgProc(HWND hDlg, WORD Msg, WORD wParam, LONG lParam)
{
switch (Msg)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch (wParam)
{
case IDCANCEL:
case IDOK:
EndDialog(hDlg, TRUE);
return TRUE;
}
break;
}
return FALSE;
}
//-------------------------------------------------------------------------
//FUNCTION:
//
// BOOL GetFileName(hWnd)
//
//PARMS IN:
//
// HWND hWnd; main window handle
//
//DESCRIPTION:
//
// This function invokes the 'SaveImage' dialog box.
//
//
//RETURN:
//
// TRUE if a filename was entered.
// FALSE if not.
//
//-------------------------------------------------------------------------
BOOL
GetFileName(HWND hWnd)
{
FARPROC lpThunk;
int Ret;
*AvssFileName = '\0';
// Make a proc instance of the dialog box proc and invoke it.
lpThunk = MakeProcInstance(OpenDlgProc, hInst);
Ret = DialogBox(hInst, "OpenFile", hWnd, lpThunk);
FreeProcInstance(lpThunk);
// Returns TRUE if a filename was selected. Check for a null length
// string.
if (Ret == FALSE || *AvssFileName == '\0')
return FALSE;
return TRUE;
}
//-------------------------------------------------------------------------
//FUNCTION:
//
// long FAR PASCAL OpenDlgProc(HWND hDlg, WORD Msg, WORD wParam,
// LONG lParam)
//
//PARMS IN:
//
// HWND hDlg; dialog box handle
// WORD Msg; type of message
// WORD wParam; 16-bit message parameter
// LONG lParam; 32-bit message parameter
//
//DESCRIPTION:
//
// 'SaveAs' file name dialog box.
//
//RETURN:
//
// TRUE if a message was processed.
// FALSE if not.
//-------------------------------------------------------------------------
BOOL FAR PASCAL
OpenDlgProc(HWND hDlg, WORD Msg, WORD wParam, LONG lParam)
{
static char EditText[128];
char *p;
switch (Msg)
{
case WM_INITDIALOG:
// Set the text entry control's limit to
// 127 characters.
SendDlgItemMessage(hDlg, IDD_FNAME, EM_LIMITTEXT, 127, 0L);
// Initialize it with the current file name.
lstrcpy((LPSTR)EditText, (LPSTR)AvssFileName);
SetDlgItemText(hDlg, IDD_FNAME, EditText);
return TRUE;
case WM_COMMAND:
switch (wParam)
{
case IDOK:
// Retrieve the entered file name.
GetDlgItemText(hDlg, IDD_FNAME, (LPSTR)EditText, 127);
if (*EditText)
{
// Chop off the extension,
// if present.
if ((p = strchr(EditText, '.')) != NULL)
*p = '\0';
// Build filespec with .avs
// extension.
strcpy(AvssFileName, EditText);
strcat(AvssFileName, ".avs");
EndDialog(hDlg, TRUE);
return TRUE;
}
// FALL THROUGH !!! If no
// filespec, we consider that
// the same as cancelling.
case IDCANCEL:
EndDialog(hDlg, FALSE);
return TRUE;
}
break;
}
return FALSE;
}
//-------------------------------------------------------------------------
//FUNCTION:
//
// VOID UpdateMenus(State)
//
//PARMS IN:
//
// WORD State; state value from the capture engine.
//
//DESCRIPTION:
//
// This function enables/disables the appropriate menu items based
// on the state of the capture engine. It displays the current
// state in the caption on the main window's title bar.
//
//-------------------------------------------------------------------------
VOID
UpdateMenus(WORD State)
{
BOOL bMonitor;
BOOL bCapture;
BOOL bExit;
HMENU hMenu;
char WindowCaption[48];
switch (State)
{
case ST_UNINITIALIZED:
bMonitor = MENUITEM_OFF;
bCapture = MENUITEM_OFF;
bExit = MENUITEM_ON;
break;
case ST_INITIALIZED:
bMonitor = MENUITEM_ON;
bCapture = MENUITEM_OFF;
bExit = MENUITEM_ON;
break;
case ST_MONITORING:
bMonitor = MENUITEM_ON;
bCapture = MENUITEM_ON;
bExit = MENUITEM_OFF;
break;
case ST_CAPTURING:
bMonitor = MENUITEM_OFF;
bCapture = MENUITEM_ON;
bExit = MENUITEM_OFF;
break;
default:
return;
}
// Get a handle to the main window's menu.
hMenu = GetMenu(hwndMain);
// Enable/disable menu options.
EnableMenuItem(hMenu, IDM_MONITOR, bMonitor);
EnableMenuItem(hMenu, IDM_CAPTURE, bCapture);
EnableMenuItem(hMenu, IDM_EXIT, bExit);
// Redraw the updated menu bar.
DrawMenuBar(hwndMain);
// Display the current state on the title bar.
wsprintf((LPSTR)WindowCaption, (LPSTR)"AvkCapt - %s",
(LPSTR)pStateName[State]);
SetWindowText(hwndMain, WindowCaption);
}